/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = ora_ttc8_oall8.c                                   */
/*  NOTE      =                                                    */
/*  DATE      = 2014/10/21 by songbb                               */
/*******************************************************************/

#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>

#include "frstr.h"
#include "frmem.h"
#include "frhash2.h"
#include "frcomm.h"
#include "frlog.h"

#include "conntrack.h"
#include "frct_comm.h"

#include "../../ora_core.h"
#include "../../comm/ora_comm.h"
#include "../../comm/ora_util.h"
#include "../../comm/ora_stmt.h"
#include "../ora_mar_engine.h"
#include "../ora_ttc_proto.h"
#include "../sql/ora_NUMBER.h"
#include "../sql/ora_STRING.h"
#include "../sql/ora_TIMESTAMP.h"
#include "../accessor/ora_include_accessor.h"
#include "ora_ttc7_tti_oac.h"
#include "ora_ttc7_tti_oer.h"
#include "ora_ttc7_tti_rxh.h"
#include "ora_ttc7_tti_rxd.h"
#include "ora_ttc7_tti_iov.h"
#include "ora_ttc7_oall7.h"
#include "../ttc8/ora_ttc8_oall8.h"
#include "ora_ttc7_item.h"
#include "../../comm/ora_charset.h"


/*******************************************************************************
*  FUNC     :  解析bind的值
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*           :  *p_st_stmt                           (Sql_statement)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
FR_STATIC int ora_ttc7_oall7_bind_unpack(Conntrack *p_st_conn
                                    , L7session_ora *p_st_sess
                                    , L7_ora_packet *p_st_ora_packet
                                    , Sql_statement *p_st_stmt)
{
    ORA_PRINT_INFO("unmarshal bind data\n");

    int i_loop = 0;
    char *p_bind_binary_value = NULL;
    char *p_bind_value = NULL;          // 存储字符串和数字类型
    int i_bind_value_len = 0;           // 字符串长度

    Sql_metadata_info *p_st_metadata = NULL;
    Frlist_node *p_st_node = NULL;
    Frlist_node *p_st_fiele_node = NULL;
    Sql_resultset *p_st_rs = NULL;
    Sql_field_bind *p_st_bind = NULL;
    Frdata_field *p_st_field = NULL;
    char *p_bind_index_name = NULL;

    if ((p_st_bind = (Sql_field_bind *) frmalloc(sizeof(Sql_field_bind))) == NULL)
    {
        ORA_MALLOCK_ERR;
        goto error;
    }
    memset(p_st_bind, 0x0, sizeof(Sql_field_bind));

    p_st_node = FRLIST_FIRST_NODE(&(p_st_stmt->st_metadata_bind));
    while (p_st_node)
    {
        p_st_metadata = (Sql_metadata_info *) FRLIST_GET_NODE_DATA(p_st_node);
        ORA_PRINT_INFO("unmarshal bind position %d\n", i_loop + 1);

        // 创建 Frdata_field
        if ((p_st_field = (Frdata_field *) frmalloc(sizeof(Frdata_field))) == NULL)
        {
            ORA_MALLOCK_ERR;
            goto error;
        }
        memset(p_st_field, 0x00, sizeof(Frdata_field));
        p_st_field->i_field_index = i_loop + 1;

        // 设置 Frdata_field 的 p_field_name
        if ((p_bind_index_name = (char *) frmalloc(APM_ORA_BIND_INDEX_NAME_MAXLEN * sizeof(char))) == NULL)
        {
            ORA_MALLOCK_ERR;
            goto error;
        }
        snprintf(p_bind_index_name, APM_ORA_BIND_INDEX_NAME_MAXLEN, "%s%d", APM_ORA_BIND_INDEX_NAME_PREFIX, i_loop);
        p_st_field->p_field_name = p_bind_index_name;
        p_bind_index_name = NULL;

        // em_data_type 默认设置为 FRSTRING
        p_st_field->em_data_type = FRSTRING;

        ORA_PRINT_CRIT("p_st_metadata => i_data_type:[%d] i_isnullbydescribe:[%d]\n", p_st_metadata->i_data_type, p_st_metadata->i_isnullbydescribe);
        ORA_PRINT_DTY_INFO((char *) "unmarshal bind data %s start\n", p_st_metadata->i_data_type);
        switch (p_st_metadata->i_data_type)
        {
            case ORA_DTY_VARCHAR:      // 1 0x01
            case ORA_DTY_LONG:         // 8 0x08
            case ORA_DTY_CHAR:         // 96 0x60
            case ORA_DTY_ROWID2:
            case ORA_DTY_ROWID:        // 104 0x68
            case ORA_DTY_UROWID:
                p_st_field->em_data_type = FRSTRING;
                if (ora_ttc7_item_unmarshal_req(p_st_conn, p_st_sess, p_st_ora_packet, p_st_metadata, &p_bind_binary_value, &i_bind_value_len) != FR_SUCC)
                    goto error;
                if (p_bind_binary_value == NULL || i_bind_value_len <= 0)
                {
                    p_st_field->p_field_value = frstrdup(APM_ORA_BIND_NULL);
                }
                else
                {
                    if (ora_STRING_toChar(p_bind_binary_value, (unsigned int) i_bind_value_len, &p_bind_value, &i_bind_value_len) != FR_SUCC)
                        goto error;
                    if (p_bind_value != NULL)
                        p_st_field->p_field_value = (char *) frmemdup(p_bind_value, (size_t) i_bind_value_len + 1);
                    else
                        p_st_field->p_field_value = frstrdup(APM_ORA_BIND_NULL);
                }
                break;

            case ORA_DTY_NUMBER:       // 2 0x02
            case ORA_DTY_VARNUM:       // 6 0x06
                // XXX: 校准这里的em_data_type，有可能为FRINT/FRLONG/FRFLOAT/FRDOUBLE
                p_st_field->em_data_type = FRDOUBLE;
                if (ora_ttc7_item_unmarshal_req(p_st_conn, p_st_sess, p_st_ora_packet, p_st_metadata, &p_bind_binary_value, &i_bind_value_len) != FR_SUCC)
                    goto error;
                if (p_bind_binary_value == NULL || i_bind_value_len <= 0)
                {
                    p_st_field->p_field_value = frstrdup(APM_ORA_BIND_NULL);
                }
                else
                {
                    if (ora_NUMBER_toChar(p_bind_binary_value, (unsigned int) i_bind_value_len, &p_bind_value, &i_bind_value_len) != FR_SUCC)
                        goto error;
                    if (p_bind_value != NULL)
                        p_st_field->p_field_value = (char *) frmemdup(p_bind_value, (size_t) i_bind_value_len + 1);
                    else
                        p_st_field->p_field_value = frstrdup(APM_ORA_BIND_NULL);
                }
                break;

            case ORA_DTY_DATE:          // 12 0x0c
            case ORA_DTY_TIMESTAMP:    // 180 0xb4
                p_st_field->em_data_type = FRTIME;
                if (ora_ttc7_item_unmarshal_req(p_st_conn, p_st_sess, p_st_ora_packet, p_st_metadata, &p_bind_binary_value, &i_bind_value_len) != FR_SUCC)
                    goto error;
                if (p_bind_binary_value == NULL || i_bind_value_len <= 0)
                {
                    p_st_field->p_field_value = frstrdup(APM_ORA_BIND_NULL);
                }
                else
                {
                    if (ora_TIMESTAMP_toLongLong(p_bind_binary_value, (unsigned int) i_bind_value_len, &p_bind_value) != FR_SUCC)
                        goto error;
                    if (p_bind_value != NULL)
                        p_st_field->p_field_value = frstrdup(p_bind_value);
                    else
                        p_st_field->p_field_value = frstrdup(APM_ORA_BIND_NULL);
                }
                break;

            case ORA_DTY_RAW:          // 23 0x17
                p_st_field->em_data_type = FRBLOB;
                if (ora_ttc7_item_skip_req(p_st_conn, p_st_sess, p_st_ora_packet, p_st_metadata) != FR_SUCC)
                    goto error;
                p_st_field->p_field_value = frstrdup(APM_ORA_BIND_BLOB);
                break;

            case ORA_DTY_LONG_RAW:     // 24 0x18
                p_st_field->em_data_type = FRBLOB;
                if (ora_ttc7_item_skip_req(p_st_conn, p_st_sess, p_st_ora_packet, p_st_metadata) != FR_SUCC)
                    goto error;
                p_st_field->p_field_value = frstrdup(APM_ORA_BIND_BLOB);
                break;

            case ORA_DTY_BINARY_FLOAT:// 100 0x64
                p_st_field->em_data_type = FRBLOB;
                if (ora_ttc7_item_skip_req(p_st_conn, p_st_sess, p_st_ora_packet, p_st_metadata) != FR_SUCC)
                    goto error;
                p_st_field->p_field_value = frstrdup(APM_ORA_BIND_BLOB);
                break;

            case ORA_DTY_BINARY_DOUBLE:// 101 0x65
                p_st_field->em_data_type = FRBLOB;
                if (ora_ttc7_item_skip_req(p_st_conn, p_st_sess, p_st_ora_packet, p_st_metadata) != FR_SUCC)
                    goto error;
                p_st_field->p_field_value = frstrdup(APM_ORA_BIND_BLOB);
                break;

            case ORA_DTY_RESULT_SET:   // 102 0x66
                if (ora_ttc7_item_skip_req(p_st_conn, p_st_sess, p_st_ora_packet, p_st_metadata) != FR_SUCC)
                    goto error;
                break;

            case ORA_DTY_NAMED_TYPE:   // 109 0x6d
            case ORA_DTY_NAMED_TYPE2:  // 121 0x79
                if (ora_ttc7_item_skip_req(p_st_conn, p_st_sess, p_st_ora_packet, p_st_metadata) != FR_SUCC)
                    goto error;
                break;

            case ORA_DTY_REF_TYPE:     // 111 0x6f
                if (ora_ttc7_item_skip_req(p_st_conn, p_st_sess, p_st_ora_packet, p_st_metadata) != FR_SUCC)
                    goto error;
                break;

            case ORA_DTY_CLOB:         // 112 0x70
                p_st_field->em_data_type = FRCLOB;
                if (ora_ttc7_item_skip_req(p_st_conn, p_st_sess, p_st_ora_packet, p_st_metadata) != FR_SUCC)
                    goto error;
                break;

            case ORA_DTY_BLOB:         // 113 0x71
                p_st_field->em_data_type = FRBLOB;
                if (ora_ttc7_item_skip_req(p_st_conn, p_st_sess, p_st_ora_packet, p_st_metadata) != FR_SUCC)
                    goto error;
                break;

            case ORA_DTY_BFILE:        // 114 0x72
                p_st_field->em_data_type = FRBLOB;
                if (ora_ttc7_item_skip_req(p_st_conn, p_st_sess, p_st_ora_packet, p_st_metadata) != FR_SUCC)
                    goto error;
                break;

            case ORA_DTY_TIMESTAMPTZ:  // 181 0xb5
                if (ora_ttc7_item_skip_req(p_st_conn, p_st_sess, p_st_ora_packet, p_st_metadata) != FR_SUCC)
                    goto error;
                break;

            case ORA_DTY_INTERVALYM:   // 182 0xb6
                if (ora_ttc7_item_skip_req(p_st_conn, p_st_sess, p_st_ora_packet, p_st_metadata) != FR_SUCC)
                    goto error;
                break;

            case ORA_DTY_INTERVALDS:   // 183 0xb7
                if (ora_ttc7_item_skip_req(p_st_conn, p_st_sess, p_st_ora_packet, p_st_metadata) != FR_SUCC)
                    goto error;
                break;

            case ORA_DTY_TIMESTAMPLTZ: // 231 0xe7
                if (ora_ttc7_item_skip_req(p_st_conn, p_st_sess, p_st_ora_packet, p_st_metadata) != FR_SUCC)
                    goto error;
                break;

            default:
                break;
        }
        ORA_PRINT_DTY_INFO((char *) "unmarshal bind data %s done\n", p_st_metadata->i_data_type);

        ora_free((void **) &p_bind_value);
        ora_free((void **) &p_bind_binary_value);

        p_st_fiele_node = frlist_node_create(p_st_field);
        frlist_push(&(p_st_bind->st_field_list), p_st_fiele_node);
        i_loop++;
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }

    if ((p_st_rs = frdb_get_last_resultset(p_st_stmt)) == NULL)
        goto error;
    if (frdb_add_resultset_bind(p_st_rs, p_st_bind) != FR_SUCC)
        goto error;
    p_st_bind = NULL;

    ORA_PRINT_INFO("leave ora_ttc7_oall7_bind_unpack\n");

    return FR_SUCC;
error:
    frdb_field_bind_free(&p_st_bind);
    ora_free((void **) &p_bind_index_name);
    ora_free((void **) &p_bind_value);
    ora_free((void **) &p_bind_binary_value);
    ora_frdata_free(&p_st_field);
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  分析长连接情况下0x0347的sql请求包
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __ora_ttc7_oall7_analyze_req_jdbc(Conntrack *p_st_conn
                                                , L7session_ora *p_st_sess
                                                , L7_ora_packet *p_st_ora_packet)
{
    ORA_PRINT_INFO("enter __ora_ttc7_oall7_analyze_req_jdbc\n");
    char c_tmp = 0;
    char c_sql_flag = 0;
    char c_dblink_flag = 0;
    char arr_sql_head[10] = {'\0'};
    char *p_tmp = NULL;
    short s_tmp = 0;
    int i_tmp = 0;
    int i_sql_len = 0;
    int i_dblink_len = 0;
    int i_inVector_len = 0;
    int i_defCols_len = 0;
    int i_numberOfBindPositions_len = 0;
    long long ll_options = 0LL;
    int i_CHR_conversion_flags_old = p_st_sess->i_CHR_conversion_flags;
    int i_useCLR_big_chunks_old = p_st_sess->i_useCLR_big_chunks;

    if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_tmp) != FR_SUCC) // seqNumber
        goto error;
    if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_options) != FR_SUCC) // options
        goto error;
    if (ora_mar_unmarshalSWORD(p_st_sess, p_st_ora_packet, &i_tmp) != FR_SUCC) // cursor
        goto error;
    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_sql_flag) != FR_SUCC) // sqlStmt.flag
        goto error;
    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_sql_len) != FR_SUCC) // sqlStmt.length
        goto error;
    // 需要存在sql语句的情况下进行判断
    if (c_sql_flag == APM_ORA_NULLPTR || i_sql_len <= 0)
        goto error;
    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_dblink_flag) != FR_SUCC) // dbLink.flag
        goto error;
    // 使用非dblink的请求进行判断
    if (c_dblink_flag == APM_ORA_PTR)
        goto error;
    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_dblink_len) != FR_SUCC) // dbLink.length
        goto error;
    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) != FR_SUCC) // inVector.flag
        goto error;
    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_inVector_len) != FR_SUCC) // inVector.length
        goto error;
    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) != FR_SUCC) // outVec.flag
        goto error;
    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_tmp) != FR_SUCC) // outVector.length
        goto error;
    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) != FR_SUCC) // outVecRetO2U
        goto error;
    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) != FR_SUCC) // defines.flag
        goto error;
    if (ora_mar_unmarshalSWORD(p_st_sess, p_st_ora_packet, &i_defCols_len) != FR_SUCC) // defCols
        goto error;
    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) != FR_SUCC) // binds.flag
        goto error;
    if (ora_mar_unmarshalSWORD(p_st_sess, p_st_ora_packet, &i_numberOfBindPositions_len) != FR_SUCC) // numberOfBindPositions
        goto error;

    if (p_st_sess->i_CHR_conversion_flags == APM_ORA_FLAG_UNSET || (p_st_sess->i_CHR_conversion_flags == FR_YES && p_st_sess->i_useCLR_big_chunks == APM_ORA_FLAG_UNSET))
    {
        if (p_st_sess->i_CHR_conversion_flags == APM_ORA_FLAG_UNSET)
        {
            if (bytebuff_remaining(p_st_ora_packet->p_st_packet) < 10)
                goto error;
            if (bytebuff_peek_bytes(p_st_ora_packet->p_st_packet, arr_sql_head, 10) != FR_SUCC)
                goto error;
            if (ora_is_sql(arr_sql_head, 10) == FR_SUCC)
                p_st_sess->i_CHR_conversion_flags = FR_NO;
            else
                p_st_sess->i_CHR_conversion_flags = FR_YES;
        }

        if (p_st_sess->i_CHR_conversion_flags == FR_YES && p_st_sess->i_useCLR_big_chunks == APM_ORA_FLAG_UNSET)
        {
            int i_ret = 0;
            if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_tmp) != FR_SUCC)
                goto error;
            if (ora_mar_escapeSequenceNull(s_tmp, &i_ret) != FR_SUCC)
                goto error;
            if (i_ret != 1 && s_tmp == 0xfe)
            {
                if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_tmp) != FR_SUCC)
                    goto error;
                p_st_sess->i_useCLR_big_chunks = s_tmp <= 4 ? FR_YES : FR_NO;
                if (bytebuffer_backspace(p_st_ora_packet->p_st_packet, 1) != FR_SUCC)
                    goto error;
            }
            if (bytebuffer_backspace(p_st_ora_packet->p_st_packet, 1) != FR_SUCC)
                goto error;
        }

        ORA_PRINT_DBG("set i_CHR_conversion_flags = %s, i_useCLR_big_chunks = %s\n",
                      p_st_sess->i_CHR_conversion_flags == APM_ORA_FLAG_UNSET ? "UNSET" : (p_st_sess->i_CHR_conversion_flags == FR_YES ? "FR_YES" : "FR_NO"),
                      p_st_sess->i_useCLR_big_chunks == APM_ORA_FLAG_UNSET ? "UNSET" : (p_st_sess->i_useCLR_big_chunks == FR_YES ? "FR_YES" : "FR_NO"));
    }

    if (ora_mar_unmarshalCHR(i_sql_len, p_st_sess, p_st_ora_packet, &p_tmp, &i_tmp) == FR_SUCC) // sqlStmt
    {
        if (ora_is_sql(p_tmp, i_tmp) != FR_SUCC)
        {
            ora_free((void **) &p_tmp);
            goto error;
        }
        if (ora_is_sql_select(p_tmp, i_tmp) != FR_SUCC)
        {
            ora_free((void **) &p_tmp);
            ORA_PRINT_DBG("is not select sql\n");
            i_CHR_conversion_flags_old = p_st_sess->i_CHR_conversion_flags;
            i_useCLR_big_chunks_old = p_st_sess->i_useCLR_big_chunks;
            goto error;
        }
        ora_free((void **) &p_tmp);
    }
    else
        goto error;

    if (ora_mar_unmarshalUB4Array(i_inVector_len, p_st_sess, p_st_ora_packet) != FR_SUCC) // inVector
        goto error;

    return FR_SUCC;
error:
    p_st_sess->i_CHR_conversion_flags = i_CHR_conversion_flags_old;
    p_st_sess->i_useCLR_big_chunks = i_useCLR_big_chunks_old;
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  解析0x0347的sql请求包
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*           :  *p_st_hash_report                    (数据上报)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_ttc7_oall7_unpack0347_req(Conntrack *p_st_conn
                                , L7session_ora *p_st_sess
                                , L7_ora_packet *p_st_ora_packet
                                , Frhash_header *p_st_hash_report)
{
    L7_session *p_st_session = frct_get_session(p_st_conn);
    L7session_ora_private *p_st_session_private = (L7session_ora_private *) frct_get_session_private(p_st_session);
    L7_ora_curr_session *p_st_curr_sess = p_st_session_private->p_st_curr_sess;
    Sql_statement *p_st_stmt = NULL;
    Sql_resultset *p_st_rs = NULL;

    if (p_st_sess->i_use_special_field == FR_NO && (p_st_sess->i_CHR_conversion_flags == APM_ORA_FLAG_UNSET ||
                                                    p_st_sess->i_useCLR_big_chunks == APM_ORA_FLAG_UNSET))
    {
        int i_analyze_start_pos = bytebuff_getPosition(p_st_ora_packet->p_st_packet);
        if (__ora_ttc7_oall7_analyze_req_jdbc(p_st_conn, p_st_sess, p_st_ora_packet) != FR_SUCC)
            return FR_FAIL;
        if (bytebuff_setPosition(p_st_ora_packet->p_st_packet, i_analyze_start_pos) != FR_SUCC)
            return FR_FAIL;
    }

    char c_tmp = 0;
    short s_tmp = 0;
    int i_tmp = 0;
    char *p_tmp = NULL;

    long long ll_options = 0LL;
    unsigned long ul_curr_cursor = 0L;
    int i_sql_len = 0;
    int i_dblink_len = 0;
    int i_inVector_len = 0;
    char *p_sql = NULL;
    unsigned int ui_sql_utf8_len = 0;
    int i_loop = 0;
    int i_defCols_len = 0;
    int i_numberOfBindPositions_len = 0;
    int i_report_stmt_req = FR_NO;
    int i_sql_exists = FR_NO;
    int i_reported_last_resp = FR_NO;
    int i_set_sql = FR_NO;
    int i_set_metadata = FR_NO;
    int i_set_bind_value = FR_NO;
    int i_oci_stmt_req_skip4_ttc7_suppose = APM_ORA_FLAG_UNSET;
    int i_sql_len_pktoffset = 0;

    if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_tmp) != FR_SUCC) // seqNumber
        goto error;

    if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_options) != FR_SUCC) // options
        goto error;
    // TODO: 判断autocommit

    if (ora_mar_unmarshalSWORD(p_st_sess, p_st_ora_packet, &i_tmp) != FR_SUCC) // cursor
        goto error;

    ul_curr_cursor = (unsigned long) i_tmp;

    // 从当前的列表中根据 cursor 获取 Ora_statement
    if ((p_st_stmt = frdb_get_statement(p_st_session_private->p_hash_stmt, ul_curr_cursor)) == NULL)
    {
        ORA_PRINT_EMERG("can not find current cursor:[%lu]\n", ul_curr_cursor);
        ORA_FRLOG_ERROR("can not find current cursor:[%lu]", ul_curr_cursor);
        goto error;
    }

    p_st_curr_sess->ul_cursor = ul_curr_cursor;

    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) != FR_SUCC) // sqlStmt.flag
        goto error;

    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_sql_len) != FR_SUCC) // sqlStmt.length
        goto error;

    if (p_st_sess->i_use_special_field == FR_YES && p_st_sess->i_send_typerep == FR_NO && p_st_sess->i_ptr_len == APM_ORA_PTR_LEN_8)
    {
        // 记录当前的offset
        i_sql_len_pktoffset = bytebuff_getPosition(p_st_ora_packet->p_st_packet);
detect_oci_stmt_req_skip4:
        if (p_st_sess->i_oci_stmt_req_skip4_ttc7 == APM_ORA_FLAG_UNSET)
        {
            if (i_oci_stmt_req_skip4_ttc7_suppose == APM_ORA_FLAG_UNSET)
            {
                ORA_PRINT_DBG("set i_oci_stmt_req_skip4_ttc7_suppose FR_NO\n");
                i_oci_stmt_req_skip4_ttc7_suppose = FR_NO;
            }
            else if (i_oci_stmt_req_skip4_ttc7_suppose == FR_NO)
            {
                ORA_PRINT_DBG("set i_oci_stmt_req_skip4_ttc7_suppose FR_YES\n");
                i_oci_stmt_req_skip4_ttc7_suppose = FR_YES;
            }
            else if (i_oci_stmt_req_skip4_ttc7_suppose == FR_YES)
            {
                ORA_PRINT_ALERT("can not tell i_oci_stmt_req_skip4_ttc7_suppose\n");
                goto error;
            }

            // 重新设置offset
            if (bytebuff_setPosition(p_st_ora_packet->p_st_packet, i_sql_len_pktoffset) != FR_SUCC)
                goto error;
        }

        if (p_st_sess->i_oci_stmt_req_skip4_ttc7 == FR_YES || i_oci_stmt_req_skip4_ttc7_suppose == FR_YES)
        {
            ORA_PRINT_DBG("skip 4 bytes after sqlStmt.length\n");
            if (ora_mar_skip(p_st_ora_packet, 4) != FR_SUCC)
                goto error;
        }
    }

    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) != FR_SUCC) // dbLink.flag
        goto error;

    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_dblink_len) != FR_SUCC) // dbLink.length
        goto error;

    if (p_st_sess->i_oci_stmt_req_skip4_ttc7 == FR_YES || i_oci_stmt_req_skip4_ttc7_suppose == FR_YES)
    {
        ORA_PRINT_DBG("skip 4 bytes after dbLink.length\n");
        if (ora_mar_skip(p_st_ora_packet, 4) != FR_SUCC)
            goto error;
    }

    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) != FR_SUCC) // inVector.flag
        goto error;
    if (p_st_sess->i_use_special_field == FR_YES &&
            p_st_sess->i_send_typerep == FR_NO &&
            p_st_sess->i_ptr_len == APM_ORA_PTR_LEN_8 &&
            p_st_sess->i_oci_stmt_req_skip4_ttc7 == APM_ORA_FLAG_UNSET &&
            c_tmp != 1)
        goto detect_oci_stmt_req_skip4;


    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_inVector_len) != FR_SUCC) // inVector.length
        goto error;

    if (p_st_sess->i_oci_stmt_req_skip4_ttc7 == FR_YES || i_oci_stmt_req_skip4_ttc7_suppose == FR_YES)
    {
        ORA_PRINT_DBG("skip 4 bytes after inVector.length\n");
        if (ora_mar_skip(p_st_ora_packet, 4) != FR_SUCC)
            goto error;
    }

    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) != FR_SUCC) // outVec.flag
        goto error;

    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_tmp) != FR_SUCC) // outVector.length
        goto error;

    if (p_st_sess->i_oci_stmt_req_skip4_ttc7 == FR_YES || i_oci_stmt_req_skip4_ttc7_suppose == FR_YES)
    {
        ORA_PRINT_DBG("skip 4 bytes after outVector.length\n");
        if (ora_mar_skip(p_st_ora_packet, 4) != FR_SUCC)
            goto error;
    }

    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) != FR_SUCC) // outVecRetO2U
        goto error;

    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) != FR_SUCC) // defines.flag
        goto error;

    if (ora_mar_unmarshalSWORD(p_st_sess, p_st_ora_packet, &i_defCols_len) != FR_SUCC) // defCols
        goto error;

    if (p_st_sess->i_oci_stmt_req_skip4_ttc7 == FR_YES || i_oci_stmt_req_skip4_ttc7_suppose == FR_YES)
    {
        ORA_PRINT_DBG("skip 4 bytes after defCols\n");
        if (ora_mar_skip(p_st_ora_packet, 4) != FR_SUCC)
            goto error;
    }

    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) != FR_SUCC) // binds.flag
        goto error;

    if (ora_mar_unmarshalSWORD(p_st_sess, p_st_ora_packet, &i_numberOfBindPositions_len) != FR_SUCC) // numberOfBindPositions
        goto error;

    if (p_st_sess->i_oci_stmt_req_skip4_ttc7 == FR_YES || i_oci_stmt_req_skip4_ttc7_suppose == FR_YES)
    {
        ORA_PRINT_DBG("skip 4 bytes after numberOfBindPositions\n");
        if (ora_mar_skip(p_st_ora_packet, 4) != FR_SUCC)
            goto error;
    }

    if (p_st_stmt->p_sql != NULL)
        i_sql_exists = FR_YES;

    if (i_sql_len > 0)
    {
        if (ora_mar_unmarshalCHR(i_sql_len, p_st_sess, p_st_ora_packet, &p_tmp, &i_tmp) == FR_SUCC) // sqlStmt
        {
            if (p_tmp)
            {
                if (ora_str_to_utf8(p_st_sess, p_st_sess->s_cli_charset_out, p_tmp, (unsigned int) i_tmp, &p_sql, &ui_sql_utf8_len) != FR_SUCC)
                    goto error;

                // 如果stmt中已存在sql的话，则先上报之前的信息
                if (i_sql_exists == FR_YES)
                {
                    if (ora_report_stmt_resp(p_st_conn, p_st_sess, p_st_stmt, p_st_hash_report, FR_YES) != FR_SUCC)
                        goto error;
                    i_reported_last_resp = FR_YES;
                }

                ORA_PRINT_WARN("sql before delete comments:[%s]\n", p_sql);
                ora_sql_delete_comments(&p_sql);
                frdb_reset_sql(p_st_stmt, p_sql);
                i_set_sql = FR_YES;
                i_report_stmt_req = FR_YES;
                ORA_PRINT_ERR("sql after delete comments:[%s]\n", p_sql);
                p_sql = NULL;
            }
            ora_free((void **) &p_tmp);
        }
        else
            goto error;
    }

    if (i_dblink_len > 0)
    {
        if (ora_mar_skipCHR(i_dblink_len, p_st_sess, p_st_ora_packet) != FR_SUCC) // dbLink
            goto error;
    }

    if (ora_mar_unmarshalUB4Array(i_inVector_len, p_st_sess, p_st_ora_packet) != FR_SUCC) // inVector
        goto error;

    ORA_PRINT_DBG("i_defCols_len:[%d]\n", i_defCols_len);
    if (i_defCols_len > 0)
    {
        frlist_remove_all(&(p_st_stmt->st_metadata_bind), frdb_metadata_node_free);
        for (i_loop = 0; i_loop < i_defCols_len; i_loop++)
        {
            if (ora_ttc7_tti_oac_unmarshal(p_st_conn, p_st_sess, p_st_ora_packet, APM_ORA_OACTYPE_DEFINE, p_st_stmt) != FR_SUCC)
                goto error;
            i_set_metadata = FR_YES;
        }
    }

    ORA_PRINT_DBG("i_numberOfBindPositions_len:[%d]\n", i_numberOfBindPositions_len);
    if (i_numberOfBindPositions_len > 0)
    {
        if (i_defCols_len == 0)
            frlist_remove_all(&(p_st_stmt->st_metadata_bind), frdb_metadata_node_free);
        for (i_loop = 0; i_loop < i_numberOfBindPositions_len; i_loop++)
        {
            if (ora_ttc7_tti_oac_unmarshal(p_st_conn, p_st_sess, p_st_ora_packet, APM_ORA_OACTYPE_BIND, p_st_stmt) != FR_SUCC)
                goto error;
            i_set_metadata = FR_YES;
        }
    }

    if (i_numberOfBindPositions_len > 0)
    {
        // 解析bind值
        ORA_PRINT_INFO("unmarshal bind value\n");
        if (i_sql_exists == FR_YES && i_reported_last_resp == FR_NO)
        {
            if (ora_report_stmt_resp(p_st_conn, p_st_sess, p_st_stmt, p_st_hash_report, FR_YES) != FR_SUCC)
                goto error;
        }
        if ((p_st_rs = frdb_get_last_resultset(p_st_stmt)) == NULL)
            goto error;
        frlist_remove_all(&(p_st_rs->st_bind_list), frdb_field_bind_node_free);
        short s_ttc_code;                                // ttc code
        while (bytebuff_remaining(p_st_ora_packet->p_st_packet) > 0)
        {
            i_report_stmt_req = FR_YES;
            if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_ttc_code) != FR_SUCC)
                goto error;
            if (s_ttc_code != APM_TTC_CODE_TTIRXD)
                goto error;
            if (ora_ttc7_oall7_bind_unpack(p_st_conn, p_st_sess, p_st_ora_packet, p_st_stmt) != FR_SUCC)
                goto error;
            i_set_bind_value = FR_YES;
        }
    }

    if (p_st_sess->i_use_special_field == FR_YES &&
            p_st_sess->i_send_typerep == FR_NO &&
            p_st_sess->i_ptr_len == APM_ORA_PTR_LEN_8 &&
            p_st_sess->i_oci_stmt_req_skip4_ttc7 == APM_ORA_FLAG_UNSET)
    {
        p_st_sess->i_oci_stmt_req_skip4_ttc7 = i_oci_stmt_req_skip4_ttc7_suppose;
        ORA_PRINT_ALERT("seti_oci_stmt_req_skip4_ttc7%s\n", p_st_sess->i_oci_stmt_req_skip4_ttc7 == FR_YES ? "FR_YES" : "FR_NO");
    }

    // 设置l4层信息
    if (frdb_set_resultset_req(p_st_stmt, FRDB_LAST, 0, bytebuff_length(p_st_ora_packet->p_st_packet), &(p_st_ora_packet->st_timestamp_first), &(p_st_ora_packet->st_timestamp_last)) != FR_SUCC)
        goto error;

    // 数据上报
    if (i_report_stmt_req == FR_YES && ora_report_stmt_req(p_st_conn, p_st_sess, p_st_stmt, p_st_hash_report) != FR_SUCC)
        goto error;

    return FR_SUCC;
error:
    ora_free((void **) &p_tmp);
    if (ora_packet_is_in_fragment(p_st_ora_packet) && ul_curr_cursor != 0L)
    {
        if (i_set_sql)
            ora_free((void **) &(p_st_stmt->p_sql));
        if (i_set_metadata)
            frlist_remove_all(&(p_st_stmt->st_metadata_bind), frdb_metadata_node_free);
        if (i_set_bind_value)
            frlist_remove_all(&(p_st_rs->st_bind_list), frdb_field_bind_node_free);
    }
    else
        ora_free((void **) &p_sql);
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  解析0x0347的sql响应包
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_ttc7_oall7_unpack_resp(Conntrack *p_st_conn
                            , L7session_ora *p_st_sess
                            , L7_ora_packet *p_st_ora_packet
                            , Frhash_header *p_st_hash_report)
{
    L7_session *p_st_session = frct_get_session(p_st_conn);
    L7session_ora_private *p_st_session_private = (L7session_ora_private *) frct_get_session_private(p_st_session);
    L7_ora_curr_session *p_st_curr_sess = p_st_session_private->p_st_curr_sess;
    Sql_statement *p_st_stmt = NULL;
    short s_ret_code;                                // return code
    int i_outVecRet = 0;
    long long ll_tmp = 0LL;
    int i_loop = 0;
    p_st_curr_sess->i_rpa_processed_flag = FR_NO;
    p_st_curr_sess->i_rxh_processed_flag = FR_NO;
    p_st_curr_sess->i_iov_processed_flag = FR_NO;

    // 直接设置解析的位置点
    if (p_st_ora_packet->i_analyze_position != 0)
    {
        bytebuff_setPosition(p_st_ora_packet->p_st_packet, p_st_ora_packet->i_analyze_position);
        p_st_curr_sess->i_rpa_processed_flag = p_st_ora_packet->i_rpa_processed_flag;
        p_st_curr_sess->i_rxh_processed_flag = p_st_ora_packet->i_rxh_processed_flag;
        p_st_curr_sess->i_iov_processed_flag = p_st_ora_packet->i_iov_processed_flag;
    }

    while(1)
    {
        if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_ret_code) == FR_FAIL)
            goto error;

        switch (s_ret_code)
        {
            case 11:
                ORA_PRINT_INFO("call 11 iov unmarshal\n");
                p_st_curr_sess->i_iov_processed_flag = FR_YES;
                if (ora_ttc7_tti_iov_unmarshal(p_st_conn, p_st_sess, p_st_ora_packet) != FR_SUCC)
                    goto error;
                // 记录当前解析完的位置点
                p_st_ora_packet->i_analyze_position = bytebuff_getPosition(p_st_ora_packet->p_st_packet);
                p_st_ora_packet->i_iov_processed_flag = FR_YES;

                if (bytebuff_remaining(p_st_ora_packet->p_st_packet) == 0)
                    goto success;
                break;

            case 6:
                ORA_PRINT_INFO("call 6  rxh unmarshal\n");
                p_st_curr_sess->i_rxh_processed_flag = FR_YES;
                if ((p_st_stmt = ora_get_current_stmt(p_st_conn)) == NULL)
                    goto error;
                if (ora_ttc7_tti_rxh_unmarshal(p_st_conn, p_st_sess, p_st_ora_packet, p_st_stmt) != FR_SUCC)
                    goto error;
                // 记录当前解析完的位置点
                p_st_ora_packet->i_analyze_position = bytebuff_getPosition(p_st_ora_packet->p_st_packet);
                p_st_ora_packet->i_rxh_processed_flag = FR_YES;
                break;

            case 7:
                // 有请求直接以0x07开头，所以这里去掉了这个检查
//                if (p_st_curr_sess->i_rxh_processed_flag != FR_YES && p_st_curr_sess->i_iov_processed_flag != FR_YES)
//                    goto error;
                ORA_PRINT_INFO("call 7  rxd unmarshal\n");
                if (ora_ttc7_tti_rxd_unmarshal(p_st_conn, p_st_sess, p_st_ora_packet) != FR_SUCC)
                    goto error;
                // 记录当前解析完的位置点
                p_st_ora_packet->i_analyze_position = bytebuff_getPosition(p_st_ora_packet->p_st_packet);
                break;

            case 8:
                if (p_st_curr_sess->i_rpa_processed_flag)
                    goto error;
                ORA_PRINT_INFO("call 8 rpa unmarshal\n");
                if (ora_mar_unmarshalUB2(p_st_sess, p_st_ora_packet, &i_outVecRet) != FR_SUCC) // outVecRet
                    goto error;
                for (i_loop = 0; i_loop < i_outVecRet; i_loop++)
                {
                    if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_tmp) != FR_SUCC) // outVector[i]
                        goto error;
                }
                p_st_curr_sess->i_rpa_processed_flag = FR_YES;
                // 记录当前解析完的位置点
                p_st_ora_packet->i_analyze_position = bytebuff_getPosition(p_st_ora_packet->p_st_packet);
                p_st_ora_packet->i_rpa_processed_flag = FR_YES;
                break;

            case 4:
                ORA_PRINT_INFO("call 4 oer unmarshal\n");
                if (ora_ttc7_tti_oer_unmarshal(p_st_conn, p_st_sess, p_st_ora_packet, APM_ORA_SESS_IS_STMT, p_st_hash_report) == FR_FAIL)
                    goto error;
                goto success; // 直接退出循环

            case 5:
            case 9:
            case 10:
            default:
                goto error;
        }
    }

success:
    return FR_SUCC;
error:
    return FR_FAIL;
}
